package org.intrasearch.core.io;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class StraightExternalizableInputStream extends ObjectInputStream
{
    private final DataInputStream in;
    private final Map<Integer, ExternalizableProvider> handleToProvider = new HashMap<Integer, ExternalizableProvider>();

    public StraightExternalizableInputStream(InputStream in, SerializationConfig serializationConfig)
            throws IOException
    {
        super();
        this.in = new DataInputStream(new BufferedInputStream(in));
        serializationConfig.configure(new Builder());
    }

    @Override
    protected Object readObjectOverride() throws IOException, ClassNotFoundException
    {
        int handle = read();
        if (handle == 0xFF)
        {
            return null;    
        }
        ExternalizableProvider externalizableProvider = handleToProvider.get(handle);
        if (externalizableProvider == null)
        {
            throw new IllegalStateException("No externalizable provider for handle: " + handle);
        }
        return externalizableProvider.readExternal(this);
    }

    public int read(byte[] b)
            throws IOException
    {
        return in.read(b);
    }

    public int read(byte[] b, int off, int len)
            throws IOException
    {
        return in.read(b, off, len);
    }

    public void readFully(byte[] b)
            throws IOException
    {
        in.readFully(b);
    }

    public void readFully(byte[] b, int off, int len)
            throws IOException
    {
        in.readFully(b, off, len);
    }

    public int skipBytes(int n)
            throws IOException
    {
        return in.skipBytes(n);
    }

    public boolean readBoolean()
            throws IOException
    {
        return in.readBoolean();
    }

    public byte readByte()
            throws IOException
    {
        return in.readByte();
    }

    public int readUnsignedByte()
            throws IOException
    {
        return in.readUnsignedByte();
    }

    public short readShort()
            throws IOException
    {
        return in.readShort();
    }

    public int readUnsignedShort()
            throws IOException
    {
        return in.readUnsignedShort();
    }

    public char readChar()
            throws IOException
    {
        return in.readChar();
    }

    public int readInt()
            throws IOException
    {
        return in.readInt();
    }

    public long readLong()
            throws IOException
    {
        return in.readLong();
    }

    public float readFloat()
            throws IOException
    {
        return in.readFloat();
    }

    public double readDouble()
            throws IOException
    {
        return in.readDouble();
    }

    @Deprecated
    public String readLine()
            throws IOException
    {
        return in.readLine();
    }

    public String readUTF()
            throws IOException
    {
        return in.readUTF();
    }

    public int read()
            throws IOException
    {
        return in.read();
    }

    public void close()
            throws IOException
    {
        in.close();
    }

    private class Builder implements SerializationBuilder
    {
        public void addClass(Class<? extends Externalizable> externalizableClass)
        {
            addExternalizableProvider(externalizableClass, new DefaultExternalizableProvider(externalizableClass));
        }

        public <T> void addExternalizableProvider(Class<? extends T> aClass, ExternalizableProvider<T> externalizableProvider)
        {
            handleToProvider.put(handleToProvider.size(), externalizableProvider);            
        }
    }
}
